Fork me on GitHub

(QT) C++ 版本IM通信软件(客户端+服务器文本聊天、文件断点续传、在线用户搜索)

紧接着上一节课程,这次的作业是要求实现一个简易版的“QQ”,可支持“软件需求”所列出的功能。当时由于图方便便选择了QTCPSocket进行整个过程的通信(事后才知道有多坑)。服务端界面比较简单,就几个按钮一个进度条,主要在客户端实现了基本的功能和界面。整个学习和开发阶段持续了将近3个礼拜,可谓是历史悠久。总的来说功能都实现了,但是存在一定的bug,估计以后也没时间去搞了,留在这儿当做一个自我的学习记录和新手的学习借鉴Demo。

运行要求

  • 同一局域网,默认端口:1234和4321,分别是聊天服务和文件服务。
  • 服务端代码为:SocketServer.rar
  • 客户端代码为:SocketClient.rar

软件需求

  1. 支持文本消息的传输;
  2. 支持局域网内在线用户搜索的功能;
  3. 可以采用c/s或者b/s结构,也可以混合结构;
  4. 支持文件传输功能;
  5. 支持1GB大小的数据文件正确传输;
  6. 支持断点续传的功能。

主要特点为

  1. 利用QTCPSocket完成通信,包括聊天和文件上传。
  2. 仿QQ双击条目打开窗口聊天,收到消息自动弹窗。
  3. 支持拉取历史聊天记录,从服务获取,默认全时间段。
  4. 利用QLineEdit组合QPushButton实现在线用户搜索,并高亮显示。
  5. 可支持跨机器的登录与注册。
  6. 服务端推送的在线用户列表,客户端实时更新。
  7. 轻量级的sqlite数据库,无需配置额外环境。
  8. 用户下线的监听,包括正常下线和异常下线,都可捕获。
  9. 支持离线文件传输,A客户端先发送到服务端,服务端保存一份,再发送到B客户端。
  10. 支持GB级大文件的快速传输。
  11. 支持断点续传,客户端点击暂停模拟断开链接或者客户端关闭窗口或者客户端下线,点击重新发送重连服务端进行续传即可。

由于每次的C-S交互过程都涉及到数据传输格式,因此需要制定一个简单易理解的数据交换格式,如下:

数据交换格式

描述 客户端请求 服务端返回
登录 login # username # password login # login success # true(false)
注册 register # username # password register # username # register success # true(false)
聊天 chat # 发送者 # 接受者 # message chat # 发送者 # message
在线用户列表 getUserList getUserList # username1 # username2……
新连接(更换登录socket) newconnect # username 无返回
断点续传 continue # 发送者 # 接受者 # 文件总长度 # 剩余数据长度 # 文件名 无返回
历史聊天记录 record # 发送者 # 接受者 record ## 发送者 ## 接受者 ## 文本内容 ## 发送时间 ##(精确到毫秒)**

上表中,record ##用来标识每条聊天记录的切分点,因为涉及到N多条聊天记录。
末尾的**用来标识聊天记录结束,是结束符,由于聊天记录也许会很大,因此需要用来判断是否需要分包接收服务返回记录。


服务端介绍

  • 登录与注册

登录与注册

服务端使用sqlite数据库保存用户注册的账号和密码,在同一局域网内支持不同机器的登录。每次客户端发送请求服务端会给予一定的返回,然后客户端再根据这个返回值执行逻辑。

登录与注册

上图是登录表,四个字段,使用isLogin区分是否登录,socketID保存客户端句柄,注册的话插入就行。

  • 聊天

这里写图片描述

客户端A要发送消息给客户端B的时候,先发送消息到服务端,服务端拿到发送者和接受者名字后,寻找到接收者相应的socket,然后再进行转发,然后发送成功后会有返回值给发送者A,发送者A拿到返回值后确认发送成功。然后聊天的所有消息记录可以保存到数据库中,以便客户端随时远程同步消息记录。服务端此处的逻辑是:客户端发消息到主界面(在线用户列表界面),然后主界面将收到的消息根据发送者进行分发,打开不同的聊天窗口,而不是在聊天窗口接受消息,分发方式使的客户端的管理更加清晰。

这里写图片描述

  • 文件上传

文件上传

可以看到服务端会受到来自于客户端1的文件,首先保存到服务器,然后会将该文件转发到接收端dl,在途中会触发两次进度条读条,同时服务端会打印整个传输过程。

这里写图片描述
这里写图片描述

上图是断点续传的服务端触发过程以及断点续传记录保存表,若发生断点,则保存已发送数据长度为断点位置,下次续传时从记录位置开始上传。当有来自于A的同名文件到达时,先查找数据库已发送数据长度是否等于总长度,若相等则为新文件,若不相等则为续传文件。


客户端介绍

  • 客户端类图

客户端类图

  • 客户端主要工程结构

    1. Mysql类和SocketUtil类为公共类,Mysql存储一些必要数据,SocketUtil主要实现一些封装的公共函数,如connect函数;
    2. 主要实现类为Login(登录功能)、Register(注册功能)、Chat(聊天功能)、OnlineUserlist(在线用户列表和搜索功能)。这几个基础类分别继承于ISOCKETSink类,此类用作Socket操作结果的回调,其中Success和Fail方法为虚函数,基类调用实现各自的具体返回结果显示。
  • 客户端登录注册界面

登录注册这里写图片描述

  • 客户端在线用户列表和搜索界面

客户端在线用户列表和搜索界面这里写图片描述

  • 客户端聊天界面

客户端聊天界面客户端聊天界面

  • 客户端发送文件界面

客户端发送文件界面客户端发送文件界面

发送文件本项目为离线文件传送,文件发送流程为客户端->服务端->转发给客户端。当实现断点续传时,点击暂停,断开当前连接,关闭当前文件,停止发送,点击重新开始时,文件从上次断开的位置继续发送,直至文件接收完成。

  • 客户端断点续传和接收文件界面

客户端断点续传和接收文件界面客户端断点续传和接收文件界面客户端断点续传和接收文件界面


操作流程

  1. 首先打开 Tserver.exe,点击“打开聊天服务”和“打开文件服务”,剩下的服务端就不用动了,处于打开状态,继续客户端操作。
  2. 客户端打开exe,进入登录界面。点击注册,注册完成后返回登录界面进行登录。
  3. 登录成功后可以看到在线用户列表(服务端推送实时刷新),“在线用户列表”界面,搜索框输入要搜索的用户,即可高亮显示被搜索用户名。
  4. 双击用户名进行聊天,支持自己给自己发送消息,输入文本消息,点击“发送消息”,即可发送文本。
  5. 支持聊天记录查看,默认同步的是从服务获得的所有时间段的聊天记录。
  6. 点击选择文件按钮,即可选择任意类型文件,点击发送,即可在线发送文件。
  7. 点击暂停模拟断点,此时已经断开客户端socket连接。再次点击继续,从断点位置开始上传。或者断开客户端,下线或者关闭窗口,重新打开后选择同名文件即可继续完成文件续传操作。
  8. 上传完成后界面显示已发送文件名和发送成功标志。
  9. 服务端同步显示发送进度和发送成功状态。
  10. 此文件发送为离线文件发送,即客户端先发送文件到服务端,服务端非同时转发,而是接受文件完成后再将此文件发送到接收端。